package me.zhengjie.modules.web.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import me.zhengjie.config.exception.WeChatException;
import me.zhengjie.constant.ConstantUtils;
import me.zhengjie.enums.RedisKeyEnum;
import me.zhengjie.modules.system.domain.*;
import me.zhengjie.modules.system.service.*;
import me.zhengjie.modules.system.service.dto.*;
import me.zhengjie.modules.system.service.mapstruct.GroupTestExpMapper;
import me.zhengjie.modules.web.domain.AtmrListResponse;
import me.zhengjie.modules.web.domain.test.*;
import me.zhengjie.modules.web.service.ITestingService;
import me.zhengjie.modules.web.service.mybatisplus.ICompanyConfigPlusService;
import me.zhengjie.modules.web.service.mybatisplus.IExamResultPlusService;
import me.zhengjie.modules.web.service.mybatisplus.IGroupTestDetailPlusService;
import me.zhengjie.modules.web.service.mybatisplus.IWxUserPlusService;
import me.zhengjie.utils.DateUtil;
import me.zhengjie.utils.RedisUtils;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static me.zhengjie.enums.RedisKeyEnum.Enterprise;

@Service
public class TestingServiceImpl implements ITestingService {

    @Autowired
    private AtmrService atmrService;

    @Autowired
    private GroupTestService groupTestService;

    @Autowired
    private ExamOrderService orderService;

    @Autowired
    private DictDetailService dictDetailService;

    @Autowired
    private GroupTestExpMapper groupTestExpMapper;

    @Autowired
    private WxUserRecommandService wxUserRecommandService;

    @Autowired
    private WxUserService wxUserService;

    @Autowired
    private IWxUserPlusService wxUserPlusService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private IExamResultPlusService examResultPlusService;

    @Autowired
    private IGroupTestDetailPlusService groupTestDetailPlusService;

    @Autowired
    private ICompanyConfigPlusService companyConfigPlusService;

    @Override
    public List<AtmrListResponse> listNew() {
        AtmrQueryCriteria atmrQueryCriteria = new AtmrQueryCriteria();
        atmrQueryCriteria.setStatus("0");
        List<AtmrDto> atmrDtos = atmrService.queryAll(atmrQueryCriteria);
        if (CollectionUtil.isEmpty(atmrDtos)){
            return null;
        }
        List<AtmrDto> tmpList = atmrDtos.stream().filter(s -> StringUtils.isNotEmpty(s.getAtmrType())).collect(Collectors.toList());
        List<AtmrListResponse> listResponses = new ArrayList<>();
        List<DictDetailDto> dictByName = dictDetailService.getDictByName("test_type");
        Map<String, List<AtmrDto>> atmrList = tmpList.parallelStream().collect(Collectors.groupingBy(AtmrDto::getAtmrType));
        atmrList.forEach((k,v) -> {
            DictDetailDto dictDetailDto = dictByName.parallelStream().filter(s -> s.getValue().equals(k)).findFirst().orElse(null);
            if (null != dictDetailDto){
                AtmrListResponse returnMap = new AtmrListResponse();
                returnMap.setType(dictDetailDto.getLabel());
                returnMap.setData(v);
                listResponses.add(returnMap);
            }
        });
        return listResponses;
    }

    @Override
    public List<AtmrDto> list() {
        AtmrQueryCriteria atmrQueryCriteria = new AtmrQueryCriteria();
        atmrQueryCriteria.setStatus("0");
        List<AtmrDto> atmrDtos = atmrService.queryAll(atmrQueryCriteria);
        if (CollectionUtil.isEmpty(atmrDtos)){
            return null;
        }
        return atmrDtos;
    }

    @Override
    public List<AtmrTestUnitRespDTO> unitList() {
        AtmrQueryCriteria atmrQueryCriteria = new AtmrQueryCriteria();
        atmrQueryCriteria.setStatus("0");
        List<AtmrDto> atmrDtos = atmrService.queryAll(atmrQueryCriteria);
        if (CollectionUtil.isEmpty(atmrDtos)){
            return null;
        }
        List<AtmrTestUnitRespDTO> respList = new ArrayList<>();
        atmrDtos.forEach(s -> {
            AtmrTestUnitRespDTO resp = new AtmrTestUnitRespDTO();
            resp.setId(s.getId());
            resp.setName(s.getAtmrName());
            resp.setType(s.getAtmrType());
            resp.setIconUrl(s.getIconUrl());
            resp.setAgeType(s.getAgeType());
            resp.setSubTitle(s.getSubTitle());
            resp.setWebUrl(resp.getWebUrl(s.getAgeType()));
            respList.add(resp);
        });
        return respList;
    }

    @Override
    public List<AtmrTestCompanyRespDTO> companyList() {
        LambdaQueryWrapper<CompanyConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompanyConfig::getStatus,1);
        List<CompanyConfig> list = companyConfigPlusService.list(wrapper);
        if (CollectionUtil.isEmpty(list)){
            return null;
        }
        List<AtmrTestCompanyRespDTO> respList = list.stream().map(s -> {
            AtmrTestCompanyRespDTO resp = new AtmrTestCompanyRespDTO();
            resp.setName(s.getName());
            resp.setCode(s.getCode());
            return resp;
        }).collect(Collectors.toList());
        return respList;
    }

    @Override
    public List<AtmrTestResultRespDTO> getTestResultByCode(AtmrTestResultReqDTO reqDTO) {
        if (CollectionUtil.isEmpty(reqDTO.getEntCodes()) && StringUtils.isBlank(reqDTO.getEntCode())){
            throw new WeChatException("缺少参数");
        }

        Object cacheObj = redisUtils.get(RedisKeyEnum.getEnterpriseKey(reqDTO.getEntCode()));
        if (Objects.nonNull(cacheObj) && cacheObj instanceof Integer){
            throw new WeChatException("你个刷子，在刷我报警了");
        }
        List<AtmrTestResultRespDTO> respList = new ArrayList<>();
        if(Objects.isNull(cacheObj)){
            LambdaQueryWrapper<ExamResult> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ExamResult::getEntCode,reqDTO.getEntCode());
            List<ExamResult> list = examResultPlusService.list(queryWrapper);
            if (CollectionUtil.isEmpty(list)){
                redisUtils.set(RedisKeyEnum.getEnterpriseKey(reqDTO.getEntCode()),-1,60*60);
                return Collections.emptyList();
            }else {
                ExamResult examResult = list.get(0);
                AtmrTestResultRespDTO respDTO = new AtmrTestResultRespDTO();
                respDTO.setEntCode(reqDTO.getEntCode());
                respDTO.setExamResult(examResult.getExamResult());
                respDTO.setAtmrResultType(examResult.getAtmrResultType());
                respList.add(respDTO);
                redisUtils.set(RedisKeyEnum.getEnterpriseKey(reqDTO.getEntCode()),respDTO,Enterprise.getExpire());
            }
        }else {
            AtmrTestResultRespDTO respDTO = (AtmrTestResultRespDTO) cacheObj;
            respList.add(respDTO);
            return respList;
        }
        return respList;
    }

    @Override
    public AtmrDto getExamById(Integer examId) {
        return atmrService.findById(examId);
    }

    @Override
    public boolean verifyFree(Integer groupgId, String openId) {

        GroupTestDto groupTestDto = groupTestService.findById(groupgId);
        if (null == groupTestDto){
            return false;
        }
        Timestamp now = new Timestamp(System.currentTimeMillis());
        Timestamp validityFrom = groupTestDto.getValidityFrom();
        Timestamp validityTo = groupTestDto.getValidityTo();
        if (validityFrom.after(now) || validityTo.before(now)){
            throw new WeChatException("团体测评未开始或者已结束");
        }
        Integer limit = groupTestDto.getLimitNum();
        Integer limitUsed = groupTestDto.getLimitUsed();
        if (limitUsed >= limit){
            throw new WeChatException("团体测评次数已用完");
        }
        ExamOrderQueryCriteria criteria = new ExamOrderQueryCriteria();
        criteria.setTeamTestid(groupgId);
        criteria.setOpenId(openId);
        criteria.setBeAnswer(1);
        List<ExamOrderDto> examOrderDtos = orderService.queryAll(criteria);
        if (CollectionUtil.isNotEmpty(examOrderDtos)){
            throw new WeChatException("不要贪心哦,你已经测过一次了");
        }
        return true;
    }

    @Override
    public VerifyGroupTestRespDTO verifyGroupTesting(Integer groupTestId) {
        VerifyGroupTestRespDTO respDTO = new VerifyGroupTestRespDTO();

        if (Objects.isNull(groupTestId)){
            respDTO.setMsg("groupTestId is null");
            return respDTO;
        }
        GroupTest groupTest = groupTestExpMapper.selectById(groupTestId);
        if (Objects.isNull(groupTest)){
            respDTO.setMsg("groupTestId is illegal");
            return respDTO;
        }
        if (groupTest.getStatus().equals(Integer.valueOf(ConstantUtils.Valid))){
            respDTO.setMsg("团测码已无效");
            return respDTO;
        }
        Timestamp now = DateUtil.TimestampNow();
        if (groupTest.getValidityFrom().after(now)) {
            respDTO.setMsg("二维码有效期未开始");
            return respDTO;
        }
        if (groupTest.getValidityTo().before(now)) {
            respDTO.setMsg("二维码已过期");
            return respDTO;
        }
        Integer limitUsed = groupTest.getLimitUsed();
        if (Objects.isNull(limitUsed)){
            limitUsed = 0;
        }
        //校验人数
        if (limitUsed >= groupTest.getLimitNum()){
            respDTO.setMsg("使用二维码人数已到上限");
            return respDTO;
        }
        respDTO.setTestingPrice(new BigDecimal(groupTest.getPrice()));
        respDTO.setReportPrice(new BigDecimal(groupTest.getReportPrice()));
        respDTO.setCanBeUsed(true);
        return respDTO;
    }

    @Override
    public VerifyGroupTestRespDTO verifyGroupTesting(Integer groupTestId, String groupCode) {
        VerifyGroupTestRespDTO respDTO = new VerifyGroupTestRespDTO();

        if (Objects.isNull(groupTestId)){
            respDTO.setMsg("groupTestId is null");
            return respDTO;
        }
        GroupTest groupTest = groupTestExpMapper.selectById(groupTestId);
        if (Objects.isNull(groupTest)){
            respDTO.setMsg("groupTestId is illegal");
            return respDTO;
        }
        if (groupTest.getStatus().equals(Integer.valueOf(ConstantUtils.Valid))){
            respDTO.setMsg("团测码已无效");
            return respDTO;
        }
        Timestamp now = DateUtil.TimestampNow();
        if (groupTest.getValidityFrom().after(now)) {
            respDTO.setMsg("二维码有效期未开始");
            return respDTO;
        }
        if (groupTest.getValidityTo().before(now)) {
            respDTO.setMsg("二维码已过期");
            return respDTO;
        }
        Integer limitUsed = groupTest.getLimitUsed();
        if (Objects.isNull(limitUsed)){
            limitUsed = 0;
        }
        if (StringUtils.isNotBlank(groupCode)){
            GroupTestDetail groupTestDetail = groupTestDetailPlusService.getOne(new LambdaQueryWrapper<GroupTestDetail>().eq(GroupTestDetail::getSerialCode, groupCode));
            if (Objects.nonNull(groupTestDetail)){
                limitUsed = groupTestDetail.getTested();
            }
        }
        //校验人数
        if (limitUsed >= groupTest.getLimitNum()){
            respDTO.setMsg("使用二维码人数已到上限");
            return respDTO;
        }
        respDTO.setTestingPrice(new BigDecimal(groupTest.getPrice()));
        respDTO.setReportPrice(new BigDecimal(groupTest.getReportPrice()));
        respDTO.setCanBeUsed(true);
        return respDTO;
    }

    @Override
    public boolean setLockUser(WxUser user, String groupId) {
        if (StringUtils.isBlank(groupId) || "0".equals(groupId) || Objects.isNull(user)){
            return false;
        }
        GroupTestDto groupTestDto = groupTestService.findById(Integer.valueOf(groupId));
        if (Objects.isNull(groupTestDto)){
            return false;
        }
        String openId = groupTestDto.getOpenId();
        if (StringUtils.isBlank(openId) || openId.equals(user.getOpenId())){
            return false;
        }
        if (StringUtils.isNotBlank(user.getSuperior())){
            return false;
        }
        WxUserRecommand wxUserRecommand = new WxUserRecommand();
        wxUserRecommand.setOpenId(openId);
        wxUserRecommand.setObjOpenid(user.getOpenId());
        wxUserRecommand.setCreateTime(DateUtil.TimestampNow());
        wxUserRecommand.setNickName(user.getNickname());
        wxUserRecommand.setHeadPic(user.getHeadimgurl());
        try {
            wxUserRecommandService.create(wxUserRecommand);
        } catch (Exception e) {
            e.printStackTrace();
        }
        WxUser wxUser = wxUserService.findByOpenId(openId);
        WxUser weixinUser = new WxUser();
        weixinUser.setSuperiorMobile(wxUser.getMobile());
        weixinUser.setSuperiorNickName(wxUser.getNickname());
        weixinUser.setSuperiorRealName(wxUser.getRealName());
        weixinUser.setSuperior(wxUser.getOpenId());
        LambdaQueryWrapper<WxUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WxUser::getOpenId,user.getOpenId());
        return wxUserPlusService.update(weixinUser,wrapper);
    }

    @Override
    public boolean checkCompanyTesting(String entCode) {

        if (StringUtils.isBlank(entCode)){
            return true;
        }
        String[] companyArray = entCode.split("_");
        if (companyArray.length <= 1){
            return true;
        }
        String companyCode = companyArray[0];

        CompanyConfig one = companyConfigPlusService.getOne(new LambdaQueryWrapper<CompanyConfig>().eq(CompanyConfig::getCode, companyCode).eq(CompanyConfig::getStatus, 1));
        if (Objects.nonNull(one)){
            return true;
        }
        return false;
    }
}
